#include "ti_msp_dl_config.h"
#include "oled.h"
#include "fft.h"
#include "arm_math.h"
#include "math.h"
#define SAMPLE_N 1024          // 采样点数
#define FFT_N 512              // FFT 点数

#define SAMPLE_FREQ 1600000    // 采样频率，单位：Hz

// 定义存储 ADC 采样结果的数组
uint16_t sample_result[SAMPLE_N];

// 采样完成标志位，volatile 修饰符防止编译器优化
volatile bool sample_complete = false;

// 定义变量存储幅值和相位
float phase1, phase2, amp1, amp2;

// 用于显示的字符串缓冲区
volatile char message[100] = {'\0'};

// FFT 计算需要的缓冲区
float32_t fft_buffer[FFT_N * 2];
float32_t fft_result[FFT_N];  // 存储 FFT 结果
uint16_t sample_buffer[FFT_N]; // 存储每次采样的数据

int main(void)
{
    // 初始化系统配置
    SYSCFG_DL_init();

    // 初始化 OLED 屏幕，清空屏幕
    OLED_Init();
    OLED_Clear();

    // 设置 DMA 传输源地址为 ADC 模块的 FIFO
    DL_DMA_setSrcAddr(
            DMA,
            DMA_CH0_CHAN_ID,
            (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST)
    );
    // 设置 DMA 目标地址为 sample_result 数组
    DL_DMA_setDestAddr(
            DMA,
            DMA_CH0_CHAN_ID,
            (uint32_t)&sample_result[0]
    );
    // 设置每轮 DMA 传输的次数
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, SAMPLE_N / 2);
    // 使能 DMA 传输通道
    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

    // 使能 ADC 模块中断
    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);

    // 开始 ADC 转换
    DL_ADC12_startConversion(ADC12_0_INST);

    uint16_t i, j;
    float a=0;float b=0;float c=0;float d=0;int k=0;
    while (1) {
        // 等待 DMA 传输完成
        while (sample_complete == false) {
            __WFI(); // 进入低功耗等待模式，等待中断唤醒
        }
        // 复位采样完成标志
        sample_complete = false;

        // 提取第一组采样数据（奇数索引）
        for (i = 0; i < SAMPLE_N/2; i++) {
            sample_buffer[i] = sample_result[2*i];
        }

        // 计算第一组采样数据的 FFT
        fft_compute(sample_buffer, fft_buffer, FFT_N, &arm_cfft_sR_f32_len512);
        // 计算第一组数据的相位
        // 采样频率Fs=1600000Hz,FFT点数N=512,待测目标信号频率50kHz
        // 有50000 = Fs * n / N
        // 又因fft_buffer中以实部虚部交错格式存储采样数据，因此数组下标32为n=16处实部、下标33为n=16处虚部
        // 相位计算方法为：phase = arctan(imag/real)
        phase1 = atan2(fft_buffer[33], fft_buffer[32]);
        // 计算幅值谱
        fft_magnitude(fft_buffer, fft_result, FFT_N);

        // 计算幅值的比例并存储
        amp1 = fft_result[16] / 77;

        // 将FFT得到的频域数据发送到串口
//        for (i = 0; i < FFT_N / 2; i++) {
//            snprintf(message, sizeof(message), (char *)"%.3f,%d\n", fft_result[i], i);
//            for (j = 0; message[j] != '\0'; j++) {
//                DL_UART_transmitDataBlocking(UART_0_INST, message[j]);
//            }
//        }

        // 提取第二组采样数据（偶数索引）
        for (i = 0; i < SAMPLE_N/2; i++) {
            sample_buffer[i] = sample_result[2*i+1];
        }

        // 计算第二组采样数据的 FFT
        fft_compute(sample_buffer, fft_buffer, FFT_N, &arm_cfft_sR_f32_len512);
        // 计算第二组数据的相位
        phase2 = atan2(fft_buffer[33], fft_buffer[32]);
        // 计算幅值谱
        fft_magnitude(fft_buffer, fft_result, FFT_N);

        // 计算幅值的比例并存储
        amp2 = fft_result[16] / 77;

        // 显示相位、幅值和相位差信息到 OLED 屏幕
//        snprintf(message, sizeof(message), (char *)"phase1: %.3f  ", phase1);
//        OLED_Display_string_5x7(0,0,message);
//        snprintf(message, sizeof(message), (char *)"phase2: %.3f  ", phase2);
//        OLED_Display_string_5x7(0,1,message);
//        snprintf(message, sizeof(message), (char *)"amp1: %.3f V  ", amp1);
//        OLED_Display_string_5x7(0,2,message);
//        snprintf(message, sizeof(message), (char *)"amp2: %.3f V  ", amp2);
//        OLED_Display_string_5x7(0,3,message);
        snprintf(message, sizeof(message), (char *)"相位差: %.2f°", 5.5 + 180 / PI * atan2(arm_sin_f32(phase1 - phase2), arm_cos_f32(phase1 - phase2)));
                OLED_Display_GB2312_string(0,5,message);
        k++;
        a+=5.5 + 180 / PI * atan2(arm_sin_f32(phase1 - phase2), arm_cos_f32(phase1 - phase2));
        if(k==100){

        b=(a/100)*(3.1415826/180);
        c = 6500000/(tan(b)*2*3.141592);
        snprintf(message, sizeof(message), (char *)"dian: %.3f°", c);
                        OLED_Display_GB2312_string(2,2,message);
                        k=0;a=0;
        }
        // 清空采样结果数组
        memset(sample_result, 0, sizeof(sample_result));

        // 重新配置 DMA 以进行下一次数据采样
        DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
        DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&sample_result[0]);
        DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID,SAMPLE_N/2);
        DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

        // 重新启动 ADC12 采样转换
        DL_ADC12_startConversion(ADC12_0_INST);
    }
}

// ADC12 采样完成的中断处理函数
void ADC12_0_INST_IRQHandler(void)
{
    // 检查 ADC12 的中断类型
    switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
        case DL_ADC12_IIDX_DMA_DONE:
            // 当 DMA 传输完成时，设置标志位并关闭 DMA 通道
            sample_complete = true;
            DL_DMA_disableChannel(DMA, DMA_CH0_CHAN_ID);
            break;
        default:
            break;
    }
}









#include "ti_msp_dl_config.h"
#include "oled.h"
#include "fft.h"
#include "arm_math.h"
#include "math.h"

#define SAMPLE_N 1024
#define FFT_N 512
#define SAMPLE_FREQ 1600000
#define TARGET_FREQ 50000
#define PI 3.1415926f
#define TARGET_BIN (uint16_t)((float)TARGET_FREQ * FFT_N / SAMPLE_FREQ)

uint16_t sample_result[SAMPLE_N];
volatile bool sample_complete = false;

float phase1, phase2, amp1, amp2;
volatile char message[100] = {'\0'};

float32_t fft_buffer[FFT_N * 2];
float32_t fft_result[FFT_N];
uint16_t sample_buffer[FFT_N];

#define PHASE_AVG_N 50
float phase_avg_buf[PHASE_AVG_N];
int phase_avg_idx = 0;
float sum_phase = 0;

float filter_phase(float new_phase) {
    sum_phase -= phase_avg_buf[phase_avg_idx];
    phase_avg_buf[phase_avg_idx] = new_phase;
    sum_phase += new_phase;
    phase_avg_idx = (phase_avg_idx + 1) % PHASE_AVG_N;
    return sum_phase / PHASE_AVG_N;
}

void apply_hanning_window(uint16_t *input, float32_t *output) {
    for (uint16_t i = 0; i < FFT_N; i++) {
        float32_t window = 0.5f * (1.0f - cosf(2 * PI * i / (FFT_N - 1)));
        output[2 * i] = ((float32_t)input[i] - 2048.0f) * window;
        output[2 * i + 1] = 0.0f;
    }
}

int main(void) {
    SYSCFG_DL_init();
    OLED_Init();
    OLED_Clear();

    DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
    DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&sample_result[0]);
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, SAMPLE_N / 2);
    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);

    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
    DL_ADC12_startConversion(ADC12_0_INST);

    while (1) {
        while (!sample_complete) __WFI();
        sample_complete = false;

        for (uint16_t i = 0; i < SAMPLE_N / 2; i++) {
            sample_buffer[i] = sample_result[2 * i];
        }
        apply_hanning_window(sample_buffer, fft_buffer);
        fft_compute(sample_buffer, fft_buffer, FFT_N, &arm_cfft_sR_f32_len512);
        phase1 = atan2f(fft_buffer[2 * TARGET_BIN + 1], fft_buffer[2 * TARGET_BIN]);
        fft_magnitude(fft_buffer, fft_result, FFT_N);
        amp1 = fft_result[TARGET_BIN] / 77;

        for (uint16_t i = 0; i < SAMPLE_N / 2; i++) {
            sample_buffer[i] = sample_result[2 * i + 1];
        }
        apply_hanning_window(sample_buffer, fft_buffer);
        fft_compute(sample_buffer, fft_buffer, FFT_N, &arm_cfft_sR_f32_len512);
        phase2 = atan2f(fft_buffer[2 * TARGET_BIN + 1], fft_buffer[2 * TARGET_BIN]);
        fft_magnitude(fft_buffer, fft_result, FFT_N);
        amp2 = fft_result[TARGET_BIN] / 77;

        float delta_phase = phase1 - phase2;
        if (delta_phase > PI) delta_phase -= 2 * PI;
        if (delta_phase < -PI) delta_phase += 2 * PI;
        float phase_deg = filter_phase(delta_phase * 180.0f / PI);

        snprintf(message, sizeof(message), "相位差: %.2f°", phase_deg);
        OLED_Display_GB2312_string(0, 5, message);

        float phase_rad = phase_deg * PI / 180.0f;
        float L = 1.0f / (2 * PI * TARGET_FREQ * tanf(phase_rad));
        snprintf(message, sizeof(message), "电感: %.3fuH", L * 1e6f);
        OLED_Display_GB2312_string(2, 2, message);

        memset(sample_result, 0, sizeof(sample_result));
        DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
        DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&sample_result[0]);
        DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, SAMPLE_N / 2);
        DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
        DL_ADC12_startConversion(ADC12_0_INST);
    }
}

void ADC12_0_INST_IRQHandler(void) {
    switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
        case DL_ADC12_IIDX_DMA_DONE:
            sample_complete = true;
            DL_DMA_disableChannel(DMA, DMA_CH0_CHAN_ID);
            break;
        default:
            break;
    }
}











#include "ti_msp_dl_config.h"
#include "oled.h"
#include "fft.h"
#include "arm_math.h"
#include "math.h"

#define SAMPLE_N 1024
#define FFT_N 512
#define SAMPLE_FREQ 1600000
#define SIGNAL_FREQ 65000.0f
#define R_VALUE 100.0f
#define PHASE_AVG_COUNT 100

uint16_t sample_result[SAMPLE_N];
volatile bool sample_complete = false;

float phase1, phase2, amp1, amp2;
volatile char message[100] = {'\0'};
float32_t fft_buffer[FFT_N * 2];
float32_t fft_result[FFT_N];
uint16_t sample_buffer[FFT_N];

float wrap_phase(float x) {
    while (x > PI) x -= 2 * PI;
    while (x < -PI) x += 2 * PI;
    return x;
}

int main(void)
{
    SYSCFG_DL_init();
    OLED_Init();
    OLED_Clear();

    DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
    DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&sample_result[0]);
    DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, SAMPLE_N / 2);
    DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
    NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
    DL_ADC12_startConversion(ADC12_0_INST);

    uint16_t i;
    float accumulated_phase = 0, avg_phase_rad = 0, capacitance = 0;
    int sample_counter = 0;

    while (1) {
        while (!sample_complete) {
            __WFI();
        }
        sample_complete = false;

        for (i = 0; i < SAMPLE_N / 2; i++) {
            sample_buffer[i] = sample_result[2 * i];
        }
        fft_compute(sample_buffer, fft_buffer, FFT_N, &arm_cfft_sR_f32_len512);
        phase1 = atan2f(fft_buffer[33], fft_buffer[32]);

        for (i = 0; i < SAMPLE_N / 2; i++) {
            sample_buffer[i] = sample_result[2 * i + 1];
        }
        fft_compute(sample_buffer, fft_buffer, FFT_N, &arm_cfft_sR_f32_len512);
        phase2 = atan2f(fft_buffer[33], fft_buffer[32]);

        float delta_phase = wrap_phase(phase1 - phase2);
        float delta_deg = delta_phase * (180.0f / PI);
        snprintf(message, sizeof(message), "相位差: %.2f°", delta_deg);
        OLED_Display_GB2312_string(0, 5, message);

        accumulated_phase += delta_phase;
        sample_counter++;

        if (sample_counter >= PHASE_AVG_COUNT) {
            avg_phase_rad = accumulated_phase / PHASE_AVG_COUNT;
            capacitance = tanf(avg_phase_rad) / (2 * PI * SIGNAL_FREQ * R_VALUE);

            snprintf(message, sizeof(message), "Cap: %.3fnF", capacitance * 1e9f);
            OLED_Display_GB2312_string(2, 2, message);

            accumulated_phase = 0;
            sample_counter = 0;
        }

        memset(sample_result, 0, sizeof(sample_result));
        DL_DMA_setSrcAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)DL_ADC12_getFIFOAddress(ADC12_0_INST));
        DL_DMA_setDestAddr(DMA, DMA_CH0_CHAN_ID, (uint32_t)&sample_result[0]);
        DL_DMA_setTransferSize(DMA, DMA_CH0_CHAN_ID, SAMPLE_N / 2);
        DL_DMA_enableChannel(DMA, DMA_CH0_CHAN_ID);
        DL_ADC12_startConversion(ADC12_0_INST);
    }
}

void ADC12_0_INST_IRQHandler(void)
{
    switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
        case DL_ADC12_IIDX_DMA_DONE:
            sample_complete = true;
            DL_DMA_disableChannel(DMA, DMA_CH0_CHAN_ID);
            break;
        default:
            break;
    }
}
